"""
Pytest 配置和共享 fixtures

提供测试所需的数据库会话、测试客户端、测试用户等。
"""
import pytest
import os
from typing import Generator
from fastapi.testclient import TestClient
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, Session
from sqlalchemy.pool import StaticPool

from app.main import app
from app.models.database import Base
from app.api.deps import get_db
from app.models.user import User
from app.core.security import get_password_hash

# 使用内存 SQLite 数据库进行测试
SQLALCHEMY_TEST_DATABASE_URL = "sqlite:///:memory:"

engine = create_engine(
    SQLALCHEMY_TEST_DATABASE_URL,
    connect_args={"check_same_thread": False},
    poolclass=StaticPool,
)
TestingSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)


@pytest.fixture(scope="function")
def db() -> Generator[Session, None, None]:
    """
    创建测试数据库会话
    
    每个测试函数都会获得一个全新的数据库会话，
    测试结束后自动清理。
    
    Yields:
        Session: 数据库会话
    """
    # 创建所有表
    Base.metadata.create_all(bind=engine)
    
    # 创建会话
    db = TestingSessionLocal()
    try:
        yield db
    finally:
        db.close()
        # 清理所有表
        Base.metadata.drop_all(bind=engine)


@pytest.fixture(scope="function")
def client(db: Session) -> Generator[TestClient, None, None]:
    """
    创建测试客户端
    
    自动注入测试数据库会话，替换生产数据库。
    
    Args:
        db: 测试数据库会话
    
    Yields:
        TestClient: FastAPI 测试客户端
    """
    def override_get_db():
        try:
            yield db
        finally:
            pass
    
    app.dependency_overrides[get_db] = override_get_db
    
    with TestClient(app) as test_client:
        yield test_client
    
    app.dependency_overrides.clear()


@pytest.fixture(scope="function")
def test_user(db: Session) -> User:
    """
    创建测试用户
    
    Args:
        db: 数据库会话
    
    Returns:
        User: 测试用户对象
    """
    user = User(
        username="testuser",
        email="test@example.com",
        hashed_password=get_password_hash("testpassword123"),
        role="user",
        is_active=True
    )
    db.add(user)
    db.commit()
    db.refresh(user)
    return user


@pytest.fixture(scope="function")
def test_admin(db: Session) -> User:
    """
    创建测试管理员用户
    
    Args:
        db: 数据库会话
    
    Returns:
        User: 管理员用户对象
    """
    admin = User(
        username="admin",
        email="admin@example.com",
        hashed_password=get_password_hash("adminpassword123"),
        role="admin",
        is_active=True
    )
    db.add(admin)
    db.commit()
    db.refresh(admin)
    return admin


@pytest.fixture(scope="function")
def auth_headers(client: TestClient, test_user: User) -> dict:
    """
    获取认证请求头
    
    自动登录测试用户并返回包含 JWT token 的请求头。
    
    Args:
        client: 测试客户端
        test_user: 测试用户
    
    Returns:
        dict: 包含 Authorization 的请求头字典
    """
    response = client.post(
        "/api/auth/login",
        data={
            "username": test_user.username,
            "password": "testpassword123"
        }
    )
    assert response.status_code == 200
    token = response.json()["access_token"]
    return {"Authorization": f"Bearer {token}"}


@pytest.fixture(scope="function")
def admin_headers(client: TestClient, test_admin: User) -> dict:
    """
    获取管理员认证请求头
    
    Args:
        client: 测试客户端
        test_admin: 管理员用户
    
    Returns:
        dict: 包含 Authorization 的请求头字典
    """
    response = client.post(
        "/api/auth/login",
        data={
            "username": test_admin.username,
            "password": "adminpassword123"
        }
    )
    assert response.status_code == 200
    token = response.json()["access_token"]
    return {"Authorization": f"Bearer {token}"}

